<template>
  <div ref="canvas"></div>
</template>

<script lang="ts" setup>
import * as THREE from "three";
import Stats from "three/examples/jsm/libs/stats.module";
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { ref, onMounted } from "vue";
import {initCamera, initDefaultLighting, initWebGLRenderer} from "@/book/ThreeUtils";
import {BufferAttribute} from "three/src/core/BufferAttribute";
import {InterleavedBufferAttribute} from "three/src/core/InterleavedBufferAttribute";
import {MorphTarget} from "three/src/animation/AnimationClip";

const canvas = ref<any>();

const scene = new THREE.Scene();
scene.add(new THREE.AmbientLight(0x333333));

const renderer = initWebGLRenderer(undefined);

const camera = initCamera(undefined);
camera.position.set(0, 15, 70);

const stat = Stats();

const orbitControl = new OrbitControls(camera, renderer.domElement);
orbitControl.update();

initDefaultLighting(scene, undefined);

let mixer: THREE.AnimationMixer = null;
let clipAction: THREE.AnimationAction = null;
let clipAction2: THREE.AnimationAction = null;

function setupModel() {
  const cubeGeom = new THREE.BoxGeometry(2, 2, 2);
  const cubeMaterial = new THREE.MeshLambertMaterial({ color : 0xff0000 });

  const cubeTarget1 = new THREE.BoxGeometry(2, 20, 2);
  const cubeTarget2 = new THREE.BoxGeometry(40, 2, 2);

  cubeGeom.morphTargetsRelative = true;
  // cubeGeom.morphAttributes = {
  //   "t1" : new Array<BufferAttribute | InterleavedBufferAttribute>(cubeGeom.getAttribute("position")),
  //   "t2" : new Array<BufferAttribute | InterleavedBufferAttribute>(cubeTarget2.getAttribute("position")),
  //   "t3" : new Array<BufferAttribute | InterleavedBufferAttribute>(cubeTarget1.getAttribute("position")),
  // };

  cubeGeom.morphAttributes[0] = new Array<BufferAttribute | InterleavedBufferAttribute>(cubeGeom.getAttribute("position"));
  cubeGeom.morphAttributes[1] = new Array<BufferAttribute | InterleavedBufferAttribute>(cubeTarget2.getAttribute("position"));
  cubeGeom.morphAttributes[2] = new Array<BufferAttribute | InterleavedBufferAttribute>(cubeTarget1.getAttribute("position"));

  cubeGeom.computeVertexNormals();

  const mesh = new THREE.Mesh(cubeGeom, cubeMaterial);
  mesh.position.set(0, 3, 0);

  scene.add(mesh);

  mixer = new THREE.AnimationMixer(mesh);

  let animationClip = THREE.AnimationClip.CreateFromMorphTargetSequence(
      'first',
      [cubeGeom.morphAttributes[0], cubeGeom.morphAttributes[1]],
      1,
      false);
  let animationClip2 = THREE.AnimationClip.CreateFromMorphTargetSequence(
      'second',
      [cubeGeom.morphAttributes[0], cubeGeom.morphAttributes[2]],
      1,
      false);

  console.log('cubeGeom.morphAttributes: ', cubeGeom.morphAttributes, '\r\n animationClip: ', animationClip, '\r\nanimationClip2: ', animationClip);

  clipAction = mixer.clipAction( animationClip ).play();
  clipAction2 = mixer.clipAction( animationClip2 ).play();

  clipAction.setLoop(THREE.LoopRepeat);
  clipAction2.setLoop(THREE.LoopRepeat);

  enableControls()
}

let mixerControls = {
  time: 0,
  timeScale: 1,
  stopAllAction: function() {mixer.stopAllAction()},
}

function enableControls() {
  var gui = new GUI();
  var mixerFolder = gui.addFolder("AnimationMixer")
  mixerFolder.add(mixerControls, "time").listen()
  mixerFolder.add(mixerControls, "timeScale", 0, 5).onChange(function (timeScale) {mixer.timeScale = timeScale});
  mixerFolder.add(mixerControls, "stopAllAction").listen()
}

setupModel();

const clock = new THREE.Clock();

const render = () => {
  stat.update();

  requestAnimationFrame(render);

  mixer.update(clock.getDelta());

  renderer.render(scene, camera);
};

onMounted(() => {
  canvas.value.appendChild(stat.domElement);
  canvas.value.appendChild(renderer.domElement);

  render();
});

</script>
